﻿/*!	@file	r_draw_core_dx11.h
	@brief	描画システム
Copyright (c) 2010 Yuya Yamaguchi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef _R_DRAW_CORE_DX11_H_
#define _R_DRAW_CORE_DX11_H_

#include "../r_draw_core.h"
#if R_TARGET_UNIQUEIS(R_TARGET_UNIQUE_WINDX11)

#include <d3d11.h>

namespace r{
	namespace draw{
		namespace dx11{
			class SwapChainDX11;
			class RenderTargetDX11;
			class DepthStencilDX11;

			class ContextDX11;
		}
	}
}
namespace r{
	namespace draw{
		namespace dx11{
			//! 描画コアクラス
			/*!
			*/
			class CoreDX11 : public r::draw::Core
			{
				RRTTI_REFLECTION_DECLARE
				friend class r::draw::Core;
			protected:
				//! コンストラクタ
				CoreDX11();
				//! デストラクタ
				virtual ~CoreDX11();
			public:
				//! r_draw_defのテクスチャフォーマットをDirectXのものに変換する
				/***/
				DXGI_FORMAT							convertImageFormat ( r_ui32 format ) const;
				//! r_draw_defのusageをDirectXのものに変換する
				/***/
				D3D11_USAGE							convertImageUsage ( r_ui32 usage ) const;
				//! r_draw_defのbindをDirectXのものに変換する
				/***/
				r_ui32								convertImageBind ( r_ui32 bind ) const;
				//! r_draw_defのbindフラグを分解してDirectXのものに変換する
				/***/
				r_ui32								convertImageBindFlag ( r_ui32 bindflag ) const;
				//! r_draw_defのtoporogyをDirectXのものに変換する
				/*!
				*/
				D3D11_PRIMITIVE_TOPOLOGY			convertPrimitiveToporogy ( r_ui32 toporogy ) const;
				//! r_draw_defのInputLayoutFormatをDirectXのものに変換する
				/*!
				*/
				DXGI_FORMAT							convertInputLayoutFormat ( r_ui32 format ) const;
				//! r_draw_defのサンプラフィルタをDirectXのものに変換する
				/*!
				*/
				D3D11_FILTER						convertFilter ( r_ui32 filter ) const;
				//! r_draw_defのサンプラアドレスモードをDirectXのものに変換する
				/*!
				*/
				D3D11_TEXTURE_ADDRESS_MODE			convertAddressMode ( r_ui32 address ) const;
				//! r_draw_defのサンプラコンペアファンクションをDirectXのものに変換する
				/*!
				*/
				D3D11_COMPARISON_FUNC				convertComparisonFunc ( r_ui32 compfunc ) const;
				//! r_draw_defのフィルモードをDirectXのものに変換する
				/*!
				*/
				D3D11_FILL_MODE						convertFillMode ( r_ui32 fill ) const;
				//! r_draw_defのカリングモードをDirectXのものに変換する
				/*!
				*/
				D3D11_CULL_MODE						convertCullMode ( r_ui32 cull ) const;
				//! r_draw_defのブレンドデータをDirectXのものに変換する
				/*!
				*/
				D3D11_BLEND							convertBlend ( r_ui32 blend ) const;
				//! r_draw_defのブレンドOPをDirectXのものに変換する
				/*!
				*/
				D3D11_BLEND_OP						convertBlendOP ( r_ui32 blendOP ) const;
				//! r_draw_defのブレンド書き込みマスクをDirectXのものに変換する
				/*!
				*/
				r_ui8								convertBlendMask ( r_ui8 mask ) const;
				//! r_draw_defの深度比較をDirectXのものに変換する
				/*!
				*/
				D3D11_COMPARISON_FUNC				convertDepthComparison ( r_ui32 depthcomp ) const;
				//! r_draw_defのステンシル処理をDirectXのものに変換する
				/*!
				*/
				D3D11_STENCIL_OP					convertStencilOp ( r_ui32 stencilop ) const;
				//! r_draw_defの深度書き込みマスクをDirectXのものに変換する
				/*!
				*/
				D3D11_DEPTH_WRITE_MASK				convertDepthWriteMask ( r_ui32 mask ) const;

				//! DirectXのイメージフォーマットをr_draw_defのものに変換する
				/***/
				ImageFormat							invertImageFormat ( r_ui32 format ) const;
				//! DirectXのUsage定義をr_draw_defのものに変換する
				/***/
				r_ui32								invertImageUsage ( r_ui32 usage ) const;
				//! DirectXのBindフラグをr_draw_defのものに変換する
				/***/
				r_ui32								invertImageBind ( r_ui32 bind ) const;
				//! DirectXのBindフラグを分解してr_draw_defのものに変換する
				/***/
				r_ui32								invertImageBindFlag ( r_ui32 bindflag ) const;
			public:
				//! D3Dデバイスの取得
				/***/
				ID3D11Device*						getD3DDevice() const;
				//! D3Dデバイスコンテキスト
				/***/
				ID3D11DeviceContext*				getD3DContext() const;
				//! featureレベルの取得
				/***/
				D3D_FEATURE_LEVEL					getFeatureLevel() const;
			protected:
				//! スワップチェインの取得
				virtual	const SwapChain*		getSwapChain() const;
				//! 2Dテクスチャの作成
				/*!
				@param	desc	[in]	テクスチャ定義データ
				@retval	作成されたテクスチャデータ
				*/
				virtual	r::draw::Texture2D*			createTexture2D ( const Texture2DDesc& desc );
				//! メモリ内のファイルデータをもとに2Dテクスチャを作成する
				/*!
				@param	desc		[in]	テクスチャ定義データ
				@param	buff		[in]	バッファデータ
				@param	buffSize	[in]	バッファサイズ
				@reval	作成されたテクスチャデータ
				*/
				virtual	r::draw::Texture2D*			createTexture2D ( const Texture2DDesc& desc, const void* buff, r_size buffSize );
				//! レンダーターゲットを作成する
				/*!
				@param	width	[in]	レンダーターゲットの横幅
				@param	height	[in]	レンダーターゲットの縦幅
				@param	format	[in]	レンダーターゲットのフォーマット
				@param	name	[in]	レンダーターゲットの名前
				@retval	レンダーターゲットクラスへのポインタ
				*/
				virtual r::draw::RenderTarget*			createRenderTarget ( r_ui32 width, r_ui32 height, ImageFormat format, const r_cstr name );
				//! 深度ステンシルビューを作成する
				/*!
				@param	width	[in]	深度ステンシルビューの横幅
				@param	height	[in]	深度ステンシルビューの縦幅
				@param	format	[in]	深度ステンシルビューのフォーマット
				@param	name	[in]	深度ステンシルビューの名前
				@retval	深度ステンシルビュークラスへのポインタ
				*/
				virtual r::draw::DepthStencil*			createDepthStencil ( r_ui32 width, r_ui32 height, ImageFormat format, const r_cstr name );
				//! サンプラステートを作成する
				/*!
				*/
				virtual	r::draw::Sampler*				createSamplerState ( const SamplerDesc& desc );
				//! ラスタステートを作成する
				/*!
				*/
				virtual	r::draw::RasterizerState*		createRasterizerState ( const RasterizerDesc& desc );
				//! ブレンドステートを作成する
				/*!
				*/
				virtual	r::draw::BlendState*			createBlendState ( const BlendStateDesc& desc );
				//! 深度ステンシルステートを作成する
				/*!
				*/
				virtual	r::draw::DepthStencilState*	createDepthStencilState ( const DepthStencilStateDesc& desc );


				//! 頂点レイアウトの作成
				/*!
				*/
				virtual	r::draw::InputLayout*			createInputLayout ( const InputLayoutDesc& layoutdesc, const VertexShader* shader );
				//! 頂点バッファの作成
				/*!
				@param	stride		[in]	1頂点サイズ
				@param	numVertex	[in]	頂点数
				*/
				virtual r::draw::VertexBuffer*			createVertexBuffer ( r_ui32 stride, r_ui32 numVertex );
				//! インデックスバッファの作成
				/*!
				@param	numIndex	[in]	インデックス数
				*/
				virtual r::draw::IndexBuffer*			createIndexBuffer ( r_ui32 numIndex );
				//! コンスタントバッファの作成
				/*!
				@param	size	[in]	定数構造体サイズ
				*/
				virtual r::draw::ConstantBuffer*		createConstantBuffer ( r_ui32 size );

				//! 頂点シェーダの作成
				/*!
				@param	buffer			[in]	シェーダコード
				@param	buffSize		[in]	シェーダコードサイズ
				@param	entryFuncName	[in]	エントリー関数名
				@param	fileName		[in]	ファイル名
				*/
				virtual	r::draw::VertexShader*			createVertexShader ( void* buffer, r_size buffSize, const r_cstr entryFuncName, const r_cstr fileName );
				//! ピクセルシェーダの作成
				/*!
				@param	buffer			[in]	シェーダコード
				@param	buffSize		[in]	シェーダコードサイズ
				@param	entryFuncName	[in]	エントリー関数名
				@param	fileName		[in]	ファイル名
				*/
				virtual	r::draw::PixelShader*			createPixelShader ( void* buffer, r_size buffSize, const r_cstr entryFuncName, const r_cstr fileName );
			protected:
				//! テクスチャの破棄
				/*!
				*/
				virtual void						destroyTexture2D ( r::draw::Texture2D* texture );
				//! レンダーターゲットの破棄
				/*!
				*/
				virtual void						destroyRenderTarget ( r::draw::RenderTarget* target );
				//! 深度ステンシルビューの破棄
				/*!
				*/
				virtual void						destroyDepthStencil ( r::draw::DepthStencil* target );
				//! サンプラステートの破棄
				/*!
				*/
				virtual	void						destroySamplerState ( r::draw::Sampler* sampler );
				//! ラスタステートの破棄
				/*!
				*/
				virtual	void						destroyRasterizerState ( r::draw::RasterizerState* raster );
				//! ブレンドステートの破棄
				/*!
				*/
				virtual	void						destroyBlendState ( r::draw::BlendState* blend );
				//! 深度ステンシルステートの破棄
				/*!
				*/
				virtual	void						destroyDepthStencilState ( r::draw::DepthStencilState* depth );

				//! 頂点レイアウトの破棄
				/*!
				*/
				virtual void						destroyInputLayout ( r::draw::InputLayout* layout );
				//! 頂点バッファの破棄
				/*!
				*/
				virtual void						destroyVertexBuffer ( r::draw::VertexBuffer* buffer );
				//! インデックスバッファの破棄
				/*!
				*/
				virtual void						destroyIndexBuffer ( r::draw::IndexBuffer* buffer );
				//! コンスタントバッファの破棄
				/*!
				*/
				virtual	void						destroyConstantBuffer ( r::draw::ConstantBuffer* buffer );

				//! 頂点シェーダの破棄
				/*!
				*/
				virtual void						destroyVertexShader ( r::draw::VertexShader* shader );
				//! フラグメントシェーダの破棄
				/*!
				*/
				virtual void						destroyPixelShader ( r::draw::PixelShader* shader );
			public:
				// システム保有データへのアクセス
				//! 最終出力用のレンダーターゲットを取得する
				/*!
				*/
				virtual	r::draw::RenderTarget*		getRenderTargetCore() const;
				//! 標準の深度ステンシルを取得する
				/*!
				*/
				virtual	r::draw::DepthStencil*		getDepthStencilCore() const;
				//! コンテキストを取得する
				/*! この関数はライブラリの提供する実行スレッド毎に異なる実体を返します。
				*/
				virtual r::draw::Context*			getContext() const;
			public:
				// システム用
				//! 描画コマンドのマージ
				/*! 全スレッドにおいて1フレーム内の全ての描画コマンドの発行を終えてから実行してください。
				*/
				virtual	void						mirgeCommand();
				//! 描画コマンドの実行
				/*! マージ済みのコマンドを実行します。
				*/
				virtual	void						executeCommand();
			public:
				//! システムエラーの検知
				virtual r_si32						checkErr() const;
			protected:
			private:
				//! D3Dデバイスの作成
				void								createDevice();
				//! コアで保有する標準レンダーターゲットを作成する
				/*!
				*/
				void								createRenderTargetView();
				//! コアで保有する標準デプスバッファを作成する
				/*!
				*/
				void								createDepthStencilView();
				//! スレッド毎のデバイスコンテキストを作成する
				/*!
				*/
				void								createThreadContext();
				//! テクスチャからシェーダリソースビューを作成する
				/*!
				*/
				ID3D11ShaderResourceView*			createShaderResourceView ( ID3D11Texture2D* texture ) const;
				//! エラーカウントをconstなのにアップする
				void								ErrUp() const;
				void								_ErrUp ( const r_si32& errcnt ) const;
			private:
				r_si32						errCount;
				//! D3D11デバイス
				ID3D11Device*				device;
				//! デバイスコンテキスト
				ID3D11DeviceContext*		context;
				//! スワップチェイン
				SwapChainDX11*		swapChain;
				//! システム内包のレンダーターゲット
				RenderTargetDX11*		coreRenderTarget;
				//! システム内包の深度ステンシル
				DepthStencilDX11*		coreDepthStencil;
				//! スレッド毎のデバイスコンテキスト
				ContextDX11*			threadContext;
			private:
				// 削除リスト
				/* 各リストはダブルバッファリングされていて1フレーム遅延して正常にデータの削除を実行する
				*/
				//! テクスチャの削除リスト
				//! レンダーターゲットの削除リスト
				//! 深度ステンシルの削除リスト
			};
		}
	}
}

#endif // R_TARGET_UNIQUEIS(R_TARGET_UNIQUE_WINDX11)

#endif // _R_DRAW_CORE_DX11_H_
